from abc import ABCMeta, abstractmethod


# 元数据 - 描述数据的数据
# 元类 - 描述类的类
# 练习: 单例模式 - 让一个类只能创建出一个对象
class Employee(metaclass=ABCMeta):
    __slots__ = ('name', )

    def __init__(self, name):
        self.name = name

    @property
    @abstractmethod
    def salary(self):
        pass


class Manager(Employee):
    __slots__ = ('name',)

    @property
    def salary(self):
        return 15000


class Programmer(Employee):
    __slots__ = ('name', '_working_hour')

    def __init__(self, name):
        super(Programmer, self).__init__(name)
        self._working_hour = 0

    @property
    def working_hour(self):
        return self._working_hour

    @working_hour.setter
    def working_hour(self, working_hour):
        self._working_hour = working_hour \
            if working_hour > 0 else 0

    @property
    def salary(self):
        return 200 * self.working_hour


class Salesman(Employee):
    __slots__ = ('name', 'sales')

    def __init__(self, name):
        super(Salesman, self).__init__(name)
        self.sales = 0

    @property
    def salary(self):
        return 1800 + self.sales * 0.05


def main():
    emps = [
        Manager('刘备'), Programmer('诸葛亮'),
        Programmer('关羽'), Salesman('张飞'),
        Salesman('马超'), Programmer('黄忠')
    ]
    for emp in emps:
        emp.gender = 'Male'
        if isinstance(emp, Programmer):
            hour = int(input(f'请输入{emp.name}本月工作时间: '))
            emp.working_hour = hour
        elif isinstance(emp, Salesman):
            sales = float(input(f'请输入{emp.name}本月销售额: '))
            emp.sales = sales
        print('%s月薪为: %.2f元' % (emp.name, emp.salary))


if __name__ == '__main__':
    main()
